在前幾天的爬蟲中,我們都是以 Python dict 的結構在儲存爬取結果,隨著爬蟲數量增加,會在越來越多的程式中使用到相同的結構來儲存資料,但同時也容易在不同爬蟲中打錯欄位名稱(例如 title 打成 titl)或者回傳結構不同的項目。好在 Scrapy 有提供一個 Item 類別,讓我們能先定義好爬取結果的欄位。
建立好專案後,專案目錄中會有一個 items.py 檔案,其中有 Scrapy 根據專案名稱自動建立的 IthomeCrawlersItem 類別,通常我會把自訂的項目類別也放在這個檔案中。每個自訂的項目都要繼承 scrapy.Item 類別,欄位則以 scrapy.Field() 來定義。
import scrapy
class IthomeCrawlersItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    pass
接下來在 item.py 檔案中加入代表文章資料的類別 IthomeArticleItem,並分別定義好每個欄位:
class IthomeArticleItem(scrapy.Item):
    url = scrapy.Field()
    title = scrapy.Field()
    author = scrapy.Field()
    publish_time = scrapy.Field()
    tags = scrapy.Field()
    content = scrapy.Field()
    view_count = scrapy.Field()
定義好 Item 後就可以在程式中使用這個類別了,使用的方式跟 dict 幾乎一樣:
import ithome_crawlers.items as items
# 初始化實例
item = item.IthomeArticleItem()
item['url'] = 'https://ithelp.ithome.com.tw/articles/10215484'
# 打錯欄位名稱會報錯:KeyError: 'IthomeArticleItem does not support field: titl'
item['titl'] = '【Day 0】前言'
item['title'] = '【Day 0】前言'
print(item)

再來把昨天的爬蟲修改為使用剛剛定義的 IthomeArticleItem 類別,完整程式碼可以到 gist 查看。
其實就是把原本的:
article = {
    'url': response.url,
    'title': title,
    'author': author,
    'publish_time': published_time,
    'tags': ','.join(tags),
    'content': content,
    'view_count': view_count
}
改成:
article = items.IthomeArticleItem()
article['url'] = response.url
article['title'] = title
article['author'] = author
article['publish_time'] = published_time
article['tags'] = ''.join(tags)
article['content'] = content
article['view_count'] = view_count